﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Aga.GestionDeArchivos.Domain.Entities;
using Aga.GestionDeArchivos.Storage;
using AutoMapper;
using Aga.GestionDeArchivos.Common;

namespace Aga.GestionDeArchivos.Services
{
    public class ClienteService : DomainServiceBase<Cliente>
    {
        /// <summary>
        /// Generars the etiquetas.
        /// </summary>
        /// <param name="clienteId">The cliente id.</param>
        /// <param name="cantidad">The cantidad.</param>
        /// <returns></returns>
        public List<CajaCliente> GenerarEtiquetas(int clienteId, int cantidad)
        {
            Cliente cliente = RepositoryFactory.CreateClienteRepository().GetById(clienteId);

            if (cliente != null)
            {
                int proximaCaja = ProximaCajaCliente(cliente);

                List<CajaCliente> nuevasCajas = new List<CajaCliente>();

                for (int numero = proximaCaja; numero < proximaCaja + cantidad; numero++)
                {
                    CajaCliente caja = new CajaCliente
                    {
                        Cliente = cliente,
                        Numero = numero,
                        CodigoBarra = String.Format("{0}-{1}", cliente.Id, numero),
                        Estado = "Creada"
                    };

                    caja.ModificationUser = caja.CreationUser = GetCurrentUser();
                    caja.ModificationDate = caja.CreationDate = DateTime.Now;

                    cliente.Cajas.Add(caja);
                    nuevasCajas.Add(caja);
                }

                RepositoryFactory.CreateClienteRepository().Save(cliente);

                return nuevasCajas;
            }

            return null;
        }

        /// <summary>
        /// Proximas the caja cliente.
        /// </summary>
        /// <param name="clienteId">The cliente id.</param>
        /// <returns></returns>
        public int ProximaCajaCliente(int clienteId)
        {
            Cliente cliente = RepositoryFactory.CreateClienteRepository().GetById(clienteId);

            return ProximaCajaCliente(cliente);
        }

        /// <summary>
        /// Proximas the caja cliente.
        /// </summary>
        /// <param name="cliente">The cliente.</param>
        /// <returns></returns>
        private int ProximaCajaCliente(Cliente cliente)
        {
            int proximaCaja = 1;

            if (cliente.Cajas.Count > 0)
                proximaCaja = cliente.Cajas.Max(c => c.Numero) + 1;

            return proximaCaja;
        }

        /// <summary>
        /// Gets the caja by id.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        public CajaCliente GetCajaById(int id)
        {
            var caja = RepositoryFactory.CreateCajaClienteRepository().GetById(id);

            return caja;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="buscar"></param>
        /// <returns></returns>
        public IQueryable<Cliente> GetAll(string buscar)
        {
            int searchTextInt;
            int? id = null;
            if (Int32.TryParse(buscar, out searchTextInt))
                id = searchTextInt;

            if (id.HasValue)
            {
                return from c in GetAll()
                       where c.Id == id.Value || c.ExId == id
                       select c;
            }
            else
            {
                return from c in GetAll()
                       where c.Nombre.ToLower().Contains(buscar.ToLower())
                       select c;
            }
        }

        public void Disable(int id)
        {
            ClienteRepository repository = RepositoryFactory.CreateClienteRepository();

            Cliente cliente = repository.GetById(id);

            if (cliente != null)
            {
                cliente.Activo = false;

                repository.Save(cliente);
            }
        }

        public Cliente Search(string searchText)
        {
            return GetAll(searchText).FirstOrDefault();
        }

        public List<KeyValuePair<int, string>> GetComboClientes()
        {
            var query = from c in RepositoryFactory.CreateClienteRepository().GetAll()
                        where c.Activo != false
                        orderby c.Nombre
                        select new { c.Id, c.Nombre };

            return query.Select(c => new KeyValuePair<int, string>(c.Id, c.Nombre)).ToList();
        }

        public void AuditarReimpresion(int clienteId, int desde, int hasta, string motivo)
        {
            RepositoryFactory.CreateReimpresionRepository().Save(new Reimpresion
            {
                Tipo = "Etiquetas de Cliente",
                Detalle = String.Format("Cliente {0} - Desde {1} hasta {2}", clienteId, desde, hasta),
                Motivo = motivo
            });
        }

        protected override RepositoryBase<Cliente> Repository
        {
            get { return RepositoryFactory.CreateClienteRepository(); }
        }

        public PagedList<Cliente> GetPage(IQueryable<Cliente> allItems, int pageIndex, int pageSize)
        {
            int totalCount = allItems.Count();
            var items = allItems.OrderBy(c => c.Nombre).Skip(pageIndex * pageSize).Take(pageSize).ToList();

            int pageCount = Convert.ToInt32(Math.Ceiling((double)totalCount / pageSize));

            return new PagedList<Cliente>(items, pageIndex, pageCount, pageSize, totalCount);
        }

        public PagedList<Cliente> GetPage(int pageIndex, int pageSize)
        {
            return GetPage(GetAll(), pageIndex, pageSize);
        }
    }

    public static class ClienteExtentions
    {
        public static string FormattedAddress(this Cliente cliente)
        {
            if (!String.IsNullOrEmpty(cliente.Direccion))
                return String.Format("{0}, {1} ({2}), {3}", cliente.Direccion, cliente.Localidad, cliente.CodigoPostal, cliente.Provincia);
            else
                return String.Empty;
        }
    }
}
